﻿using System;
using System.Collections.Generic;
using System.Text;
using daBase.Analyser;
using daSyntaxAnalyser;
using daBase.Objects.Safe;
using daSemanticAnalyser.SemanticTree;
using daStaticAnalyser.Analysers;
using daStaticAnalyser;

namespace DifferentAnalizers
{
    [AnalyserDefaultSettings("Уровень статики.", "Уровень статики класса {0} = {1}.", 10, "При высоком уровне статики возможно обозначить класс, как статический.")]
    class StaticMethodAnalyser : BaseStaticAnalyser
    {
        private string classname;
        private double staticlevel;
        private List<FileSemanticElement> analysedUnits;

        /// <summary>
        /// Сообщение об ошибке
        /// </summary>
        /// <returns>собственно, сообщение об ошибке</returns>
        protected override string ErrorMessage()
        {
            return string.Format(base.ErrorMessage(), classname, string.Format("{0}%", (int)(staticlevel * 100)));
        }

        private void Initialize()
        {
            classname = string.Empty;
            analysedUnits.Clear();
        }

        private void CheckClassStatic(FullClassTypeSemanticElement Class)
        {
            classname = Class.Name;
            int staticMethodCount = 0, methodCount = 0;
            foreach(ClassSectionSemanticElement section in Class.Sections)
                foreach (MethodSemanticElement method in section.Methods)
                {
                    methodCount++;
                    if ((method is ClassFunctionSemanticElement) || (method is ClassProcedureSemanticElement))
                        staticMethodCount++;
                }
            if (methodCount == 0)
                staticlevel = 0;
            else staticlevel = (double)staticMethodCount / methodCount;
            AddError(Class.SyntaxElement.StartInfo, Class.SyntaxElement.ToString());
//            AddError(new TokenInfo(DelphiTokens.Undefined, string.Empty, string.Format("{0}.pas", Class.Unit.Name), 1, new SafeDictionary<string,string>(x=>string.Empty), new List<string>()), string.Empty);
        }

        private void AnalyseUnit(FileSemanticElement Unit)
        {
            if (analysedUnits.Contains(Unit)) return;
            analysedUnits.Add(Unit);
            foreach (UnitSemanticElement unit in Unit.Units)
                AnalyseUnit(unit);
            foreach (CommonTypeSemanticElement type in Unit.Types)
                if (type is FullClassTypeSemanticElement)
                    CheckClassStatic(type as FullClassTypeSemanticElement);
            if (Unit is UnitSemanticElement)
            {
                UnitSemanticElement unit = Unit as UnitSemanticElement;
                foreach (CommonTypeSemanticElement type in unit.PrivateTypes)
                    if (type is FullClassTypeSemanticElement)
                        CheckClassStatic(type as FullClassTypeSemanticElement);
            }
        }

        /// <summary>
        /// Семантический анализ
        /// </summary>
        /// <param name="e">набор токенов</param>
        protected override void DoSemanticAnalyse(SemanticTreeArgs e)
        {
            if (e.Root != null)
            {
                Initialize();
                AnalyseUnit(e.Root);
            }
        }

        public StaticMethodAnalyser()
            : base()
        {
            analysedUnits = new List<FileSemanticElement>();
        }
    }
}
